/* hal_uart.h */
#ifndef __HAL_UART_H__
#define __HAL_UART_H__

#include "hal_common.h"

/* UART status with no interrupt. */
#define UART_STATUS_TX_BUSY          UART_STATUS_TX_BUSY_MASK
#define UART_STATUS_RX_BUSY          UART_STATUS_RX_BUSY_MASK
#define UART_STATUS_RX_FIFO_EMPTY    UART_STATUS_RX_EM_MASK
#define UART_STATUS_RX_FIFO_FULL     UART_STATUS_RX_FULL_MASK
#define UART_STATUS_TX_FIFO_EMPTY    UART_STATUS_TX_EM_MASK
#define UART_STATUS_TX_FIFO_FULL     UART_STATUS_TX_FULL_MASK

/* UART status with interrupt. */
#define UART_INT_RX_FRAME_ERR        UART_INT_FL_RX_FERR_MASK
#define UART_INT_RX_PARITY_ERR       UART_INT_FL_RX_PAR_MASK
#define UART_INT_CTS_SIGNAL_CHANGE   UART_INT_FL_CTS_EV_MASK
#define UART_INT_RX_FIFO_OVERRUN     UART_INT_FL_RX_OV_MASK
#define UART_INT_RX_FIFO_THRESHOLD   UART_INT_FL_RX_THD_MASK
#define UART_INT_TX_FIFO_HALF_EMPTY  UART_INT_FL_TX_HE_MASK

typedef enum
{
    UART_Parity_None = 0u,
    UART_Parity_Even = 2u,
    UART_Parity_Odd = 3u,
} UART_Parity_Type;

typedef enum
{
    UART_DataBits_5b = 0u,
    UART_DataBits_6b = 1u,
    UART_DataBits_7b = 2u,
    UART_DataBits_8b = 3u,
} UART_DataBits_Type;

typedef enum
{
    UART_StopBits_1b = 0u,
    UART_StopBits_1b5 = 1u,
    UART_StopBits_2b = 2u,
} UART_StopBits_Type;

typedef enum
{
    UART_RxFifoThreshold_1B = 1u,
    UART_RxFifoThreshold_2B = 2u,
    UART_RxFifoThreshold_3B = 3u,
    UART_RxFifoThreshold_4B = 4u,
    UART_RxFifoThreshold_5B = 5u,
    UART_RxFifoThreshold_6B = 6u,
    UART_RxFifoThreshold_7B = 7u,
    UART_RxFifoThreshold_8B = 8u,
} UART_RxFifoThreshold_Type;

typedef enum
{
    UART_BaudrateClkSrc_Alt0 = 0u,
    UART_BaudrateClkSrc_Alt1 = 1u,
    UART_BaudrateClkSrc_Alt2 = 2u, /* IBRO. 7372800 hz. 115200 x 64. */
    UART_BaudrateClkSrc_Alt3 = 3u,
} UART_BaudrateClkSrc_Type;

#define UART_IBRO_FREQ_HZ  7372800u

typedef struct
{
	UART_BaudrateClkSrc_Type BaudrateClkSrc;
	uint32_t BaudrateClkSrcHz; /* IBRO. 7372800 hz. 115200 x 64. */
	uint32_t Baudrate;

	UART_RxFifoThreshold_Type RxFifoThreshold;
    UART_DataBits_Type DataBits;
    UART_StopBits_Type StopBits;
    UART_Parity_Type   Parity;

} UART_Init_Type;

void     UART_Init(UART_Type * UARTx, UART_Init_Type * init);
void     UART_ResetRxFifo(UART_Type * UARTx);
void     UART_ResetTxFifo(UART_Type * UARTx);
void     UART_PutTxFifoData(UART_Type * UARTx, uint8_t dat);
uint8_t  UART_GetRxFifoData(UART_Type * UARTx);
uint32_t UART_GetStatus(UART_Type * UARTx);
uint32_t UART_GetRxFifoCount(UART_Type * UARTx);
uint32_t UART_GetTxFifoCount(UART_Type * UARTx);
uint32_t UART_GetInterruptStatus(UART_Type * UARTx);
void     UART_ClearInterruptStatus(UART_Type * UARTx, uint32_t flags);
void     UART_EnableInterrupts(UART_Type * UARTx, uint32_t flags, bool enable);
uint32_t UART_GetEnabledInterrupts(UART_Type * UARTx);

/* TODO: support DMA. */

#endif /* __HAL_UART_H__ */

